<?php

namespace Hx\Http;

use Hx\App;

/**
 * 请求返回类
 * Class Response
 * @package Hx\Http
 */
class Response {

    /**
     * 状态码
     * @var int
     */
    protected $status;

    /**
     * 文档类型
     * @var string
     */
    protected $contentType;

    /**
     * 头信息
     * @var array
     */
    protected $headers = array(
        'X-Powered-By' => 'PHP - Hx - 1.0'
    );

    /**
     * 构造方法
     */
    public function __construct() {
        $this->status = 200;
        $this->contentType = 'text/html;charset=UTF-8';
        #默认禁止缓存
        $this->setCache(0);
    }

    //-------------------

    /**
     * 获取状态码
     * @return int
     */
    public function getStatus() {
        return $this->status;
    }

    /**
     * 设置状态码
     * @param int $code
     * @return $this
     */
    public function setStatus($code) {
        $this->status = (int)$code;
        return $this;
    }

    //-------------------

    /**
     * 设置文档类型
     * @param string $contentType
     * @return $this
     */
    public function setContentType($contentType) {
        $this->contentType = $contentType;
        return $this;
    }

    /**
     * 获取文档类型
     * @return string
     */
    public function getContentType() {
        return $this->contentType;
    }

    //---------------

    /**
     * 设置头信息
     * @param string $k
     * @param mixed $v
     * @return $this
     */
    public function setHeader($k, $v) {
        $this->headers[$k] = $v;
        return $this;
    }

    /**
     * 获取头信息
     * @param string $key
     * @return mixed
     */
    public function getHeader($key) {
        return $this->headers[$key];
    }

    /**
     * 获取所有头信息
     * @return array
     */
    public function getHeaders() {
        return $this->headers;
    }

    //-----------------

    /**
     * 状态码描述
     * @var array
     */
    protected static $statusTexts = array(
        '100' => 'Continue',
        '101' => 'Switching Protocols',
        '200' => 'OK',
        '201' => 'Created',
        '202' => 'Accepted',
        '203' => 'Non-Authoritative Information',
        '204' => 'No Content',
        '205' => 'Reset Content',
        '206' => 'Partial Content',
        '300' => 'Multiple Choices',
        '301' => 'Moved Permanently',
        '302' => 'Found',
        '303' => 'See Other',
        '304' => 'Not Modified',
        '305' => 'Use Proxy',
        '306' => '(Unused)',
        '307' => 'Temporary Redirect',
        '400' => 'Bad Request',
        '401' => 'Unauthorized',
        '402' => 'Payment Required',
        '403' => 'Forbidden',
        '404' => 'Not Found',
        '405' => 'Method Not Allowed',
        '406' => 'Not Acceptable',
        '407' => 'Proxy Authentication Required',
        '408' => 'Request Timeout',
        '409' => 'Conflict',
        '410' => 'Gone',
        '411' => 'Length Required',
        '412' => 'Precondition Failed',
        '413' => 'Request Entity Too Large',
        '414' => 'Request-URI Too Long',
        '415' => 'Unsupported Media Type',
        '416' => 'Requested Range Not Satisfiable',
        '417' => 'Expectation Failed',
        '500' => 'Internal Server Error',
        '501' => 'Not Implemented',
        '502' => 'Bad Gateway',
        '503' => 'Service Unavailable',
        '504' => 'Gateway Timeout',
        '505' => 'HTTP Version Not Supported',
    );

    /**
     * 获取状态码的描述
     * @param int $status
     * @return string
     */
    public function getStatusText($status){
        return 'HTTP/1.1 ' . $status . ' ' .ucwords(self::$statusTexts[$status]);
    }

    //--------------------------------

    /**
     * 设置缓存
     * @param int $expire
     * @return $this
     */
    public function setCache($expire = 0) {
        if ($expire <= 0) {
            $this->headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate';
            $this->headers['Expires'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
            $this->headers['Pragma'] = 'no-cache';
        } else {
            $this->headers['Last-Modified'] = gmdate('r', time());
            $this->headers['Expires'] = gmdate('r', time() + $expire);
            $this->headers['Cache-Control'] = 'max-age=' . $expire;
            unset($this->headers['Pragma']);
        }
        return $this;
    }

    //------------------------------

    /**
     * 内容体文本
     * @var string
     */
    protected $body;

    /**
     * 设置内容文本
     * @param string $text
     * @return $this
     */
    public function setBody($text) {
        $this->body = $text;
        return $this;
    }

    /**
     * 获取内容文本
     * @return mixed
     */
    public function getBody() {
        return $this->body;
    }

    //----------------------------

    /**
     * 是否已经发送
     * @var bool
     */
    protected $isSendStatus = FALSE;

    /**
     * 判断是否已经发送
     * @return bool
     */
    public function isSend() {
        return $this->isSendStatus;
    }

    //---------------------------

    /**
     * 发送返回请求
     * @return bool
     */
    public function send() {
        #判断有没有发送
        if ($this->isSendStatus) {
            return FALSE;
        }
        #填入文档类型
        if (!$this->headers['Content-Type']) {
            $this->headers['Content-Type'] = $this->contentType;
        }
        #预设为无缓存
        if (!$this->headers['Cache-Control']) {
            self::setCache(0);
        }
        #发送状态信息
        header('HTTP/1.1 ' . $this->status . ' ' . ucwords(self::$statusTexts[$this->status]));
        header('Status: ' . $this->status . ' ' . ucwords(self::$statusTexts[$this->status]));
        #头信息
        foreach ($this->headers as $key => $value) {
            header($key . ': ' . $value);
        }
        #输出内容
        if ($this->body) {
            echo $this->body;
        }
        $this->isSendStatus = TRUE;
        return TRUE;
    }

    /**
     * 跳转请求
     * @param string $url
     * @param int $code
     */
    public function redirect($url, $code = 302) {
        $this->status = $code;
        $this->setHeader('Location', $url);
        $this->send();
    }

    /**
     * 错误请求
     * @param int $code
     * @param null|string $text
     */
    public function error($code, $text = NULL) {
        $this->status = $code;
        if (!$text || !$this->body) {
            #默认填充状态码描述
            $text = 'HTTP/1.1 ' . $this->status . ' ' .ucwords(self::$statusTexts[$this->status]);
        }
        $this->body = $text;
        $this->send();
    }

    /**
     * 转用别的路由请求
     * @param string $name
     * @param array $args
     * @return bool|mixed
     */
    public function forward($name, $args = array()) {
        $app = App::getInstance();
        #获取路由规则
        $rule = $app->getRouter()->getRule($name);
        if (!$rule) {
            return FALSE;
        }
        #调用路由的回调操作
        $controllerName = $app->getName() . '\Controller\\' . $rule['callback'][0];
        $controller = new $controllerName();
        $method = $rule['callback'][1] . 'Action';
        if (!is_callable(array($controller, $method))) {
            self::error('no executable forward controller : ' . $controllerName . '->' . $method);
        }
        return call_user_func_array(array($controllerName, $method), $args);
    }

}